package com.elastic.search;

import com.elastic.mapping.ClientFactory;
import com.elastic.util.EsUtil;
import com.elastic.util.User;
import org.elasticsearch.action.delete.DeleteRequestBuilder;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.deletebyquery.DeleteByQueryResponse;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHits;

import java.io.IOException;
import java.util.Map;

/**
 * index：create、update、delete
 * 
 * search：query（queryParser）、filter、sort、paging、highlight、facet
 * 
 * multiSearch
 * 
 * cache
 * 
 * @author xiao
 * 
 */
public class ESClient {
	private Client client;

	private String indexKey = "xiaocai";// 相当于数据库的名称

	private String type = "user";// 相当于数据库的表

	public void init() {
		// 9300 是我们java 连接的esserver 的端口。9200 是restapi 的接口
		Settings settings = ImmutableSettings.settingsBuilder()
				.put("client.transport.sniff", true).put("client", true)
				.put("data", false)
				// .put("path.data",indexPath)
				.put("cluster.name", "myClusterName")
				.put("client.transport.ping_timeout", "1000s").build();

		client = ClientFactory.getInstance();
	}

	public void close() {
		client.close();
	}

	/**
	 * 转换成json对象 json=={"id":"1","name":"aa","age":"20"}
	 * 
	 * @param user
	 * @return
	 */
	private String generateJson(User user) {
		String json = "";
		try {
			XContentBuilder contentBuilder = XContentFactory.jsonBuilder()
					.startObject();
			contentBuilder.field("id", user.getId() + "");
			contentBuilder.field("name", user.getName());
			contentBuilder.field("age", user.getAge() + "");
			json = contentBuilder.endObject().string();
			System.out.println("json==" + json);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return json;
	}

	/**
	 * 转换成json对象 {"user":{"id":"1","name":"aa","age":"20"}}
	 * 
	 * @param user
	 * @return
	 */
	private String generateJson2(User user) {
		String json = "";
		try {
			XContentBuilder contentBuilder = XContentFactory.jsonBuilder()
					.startObject();
			contentBuilder.startObject("user");
			contentBuilder.field("id", user.getId() + "");
			contentBuilder.field("name", user.getName());
			contentBuilder.field("age", user.getAge() + "");
			json = contentBuilder.endObject().endObject().string();
			System.out.println("generatero json2 ===" + json);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return json;
	}

	
	

	public static void main(String[] args) {
		ESClient client = new ESClient();
		client.init();
		User user = new User();
		user.setId(1L);
		user.setName("aa");
		user.setAge(20);

		try {
			client.update();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// client.generateJson2(user);
		// client.createIndex();
		client.close();
	}

	/**
	 * id 是每行记录生成的id 键值， 所以最好自动生成id 的时候， 利用以前每个表的主键来做。 这个id 不是用户表里面的id
	 * 字段，而是添加document 的时候，自动生成的id, 应该在添加记录的时候就去指定好
	 */
	public void getQequest() {
		GetResponse response = client.prepareGet(indexKey, type, "2").execute()
				.actionGet();
		System.out.println("id==" + response.getId());
		System.out.println("sours as string==" + response.getSourceAsString());// sours
																				// as
																				// string=={"id":"1","name":"new","age":"20"}
		System.out.println("a==" + response.getField("name"));
		System.out.println("response" + response.toString());
		Map<String, Object> sourceMap = response.getSourceAsMap();
		
	}

	public void deleteById() {
		DeleteRequestBuilder buidler = client.prepareDelete(indexKey, type,
				"AU1qwCxBcygKZ5YrguXM");
		buidler.get();// 相当于execute().actionGet();
		DeleteResponse response = client.prepareDelete(indexKey, type,
				"AU1qwCxBcygKZ5YrguXM")
		// .execute()
		// .actionGet();
				.get();
	}

	

	private XContentBuilder jsonBuilder() {
		try {
			return XContentFactory.jsonBuilder();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	private void doUpdate1() throws Exception {
		UpdateRequest updateRequest = new UpdateRequest();
		updateRequest.index(indexKey);
		updateRequest.type(type);
		updateRequest.id("1");
		updateRequest.doc(jsonBuilder().startObject()
				.field("name", "doUpdate1").endObject());
		client.update(updateRequest).get();
		// ActionFuture get
	}

	private void doUpdate2() throws Exception {
		// client.prepareUpdate("ttl", "doc", "1")
		// .setScript("ctx._source.gender = \"male\""
		// ,ScriptService.ScriptType.INLINE)
		// .get();

		client.prepareUpdate(indexKey, type, "1")
				.setDoc(jsonBuilder().startObject().field("name", "xiaocai")
						.endObject()).get();
	}

	/**
	 * 如果是添加的元素不存在，就添加IndexRequest 的键值；
	 * 如果存在了相同的id,那么indexRequest 就不会添加了。只会更新了age16
	 * @param id
	 * @throws Exception
	 */
	private void doUpdate3(String id) throws Exception {
		IndexRequest indexRequest = new IndexRequest(indexKey, type, id)
				.source(jsonBuilder().startObject().field("name", "Joe Smith")
						.field("age", "233").endObject());
		UpdateRequest updateRequest = new UpdateRequest(indexKey, type, id)
				.doc(jsonBuilder().startObject().field("age", "16")
						.endObject()).upsert(indexRequest);
		client.update(updateRequest).get();
	}
	
	
	public void add() {
		User user = new User();
		user.setId(1200L);
		user.setName("new");
		user.setAge(20);
		IndexResponse response = client.prepareIndex("xiaocai", "user", "1200")
				.setSource(generateJson(user)).execute().actionGet();
	}
	
//	private void batch(){
//		bulkRequest.add(client.prepareIndex("twitter", "tweet", "1")
//		        .setSource(jsonBuilder()
//		                    .startObject()
//		                        .field("user", "kimchy")
//		                        .field("postDate", new Date())
//		                        .field("message", "trying out Elasticsearch")
//		                    .endObject()
//		                  )
//		        );
//
//		bulkRequest.add(client.prepareIndex("twitter", "tweet", "2")
//		        .setSource(jsonBuilder()
//		                    .startObject()
//		                        .field("user", "kimchy")
//		                        .field("postDate", new Date())
//		                        .field("message", "another post")
//		                    .endObject()
//		                  )
//		        );
//
//		BulkResponse bulkResponse = bulkRequest.execute().actionGet();
//		if (bulkResponse.hasFailures()) {
//		    // process failures by iterating through each bulk response item
//		}
//	}
	
	public void search(){
		   SearchRequestBuilder searchBuilder = client.prepareSearch(indexKey);//指定多个数据库
		   searchBuilder.setTypes(type);
		
		   SearchResponse searchResponse = searchBuilder/*.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)*/
	        .setQuery(QueryBuilders.termQuery("id", "5"))// Query
	        .setQuery(QueryBuilders.termsQuery("id", "1","6"))// in query
	        //后面的条件query 会把前面的query 给覆盖掉。
	        //.setPostFilter(FilterBuilders.rangeFilter("age").from(12).to(18))   // Filter
	        .setFrom(0).setSize(60).setExplain(true)
	        .execute()
	        .actionGet();
		   
		   
		    System.out.println("searchResponse =="+searchResponse);
		    SearchHits hits = searchResponse.getHits();
	        long totalCount = hits.getHits().length;
	        long a = hits.totalHits();//总数
	        System.out.println("totalCount=="+totalCount+",a=="+a);
	        for (int i = 0; i < totalCount; i++) {
	        	 Map<String,Object> map = hits.getAt(i).getSource();
	        	 EsUtil.printMap(map);
	        }
		   
	}
	
	
	
	
	
	 /**
     * 查询记录条数
     * @return long
     */
    public long searchRecordListCount() {
        long count = 0;
        SearchHits hits = null;
        try {
           SearchRequestBuilder searchBuilder = client.prepareSearch(indexKey);//指定多个数据库
   		   searchBuilder.setTypes(type);
            SearchResponse searchResponse = searchBuilder
                    .setSearchType(SearchType.COUNT).setExplain(false)
                    .execute()
                    .actionGet();
            hits = searchResponse.getHits();
            count = hits.totalHits();
        } catch (Exception e) {
            
        }
        return count;
    }
    
   
	
	public void deleteByquery(){
		DeleteByQueryResponse response = client.prepareDeleteByQuery(indexKey)
				.setTypes(type)
		        .setQuery(QueryBuilders.termQuery("id", "5"))
		        .execute()
		        .actionGet();
	}
	
	/**
	 * elasticsearch 提供基于JSON的完整的Query DSL查询表达式(DSL即领域专用语言). 一般来说, 普通的查询如 term 或者 prefix. 另外还有混合查询如 bool
	 * 
	 */
	public static void testUpdateOrAdd(){
//		bulkRequest.add(client.prepareIndex(indexK, "tweet", "1")
//		        .setSource(jsonBuilder()
//		                    .startObject()
//		                        .field("user", "kimchy")
//		                        .field("postDate", new Date())
//		                        .field("message", "trying out Elasticsearch")
//		                    .endObject()
//		                  )
//		        );
	}
	
	
	//只有id 相同了，其他的就是更新了不管用户的id
	public void update() {
		User user = new User();
		user.setId(3L);
		user.setName("1update");
		user.setAge(20);
		IndexResponse response = client.prepareIndex("xiaocai", "user", "1")
				.setSource(generateJson(user)).execute().actionGet();
		System.out.println(response.getId());
	}
	
}
